package com.sl.core.utils;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.SneakyThrows;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class JsonMap extends HashMap<String, Object> {


    public void rebuild() {
        this.mapToEntity(this.getClass());
    }

    @SneakyThrows
    public void build() {
        entityToMap(this.getClass());
    }

    @SneakyThrows
    private void mapToEntity(Class<?> cls) {
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            String name = field.getName();
//            Class<?> type = field.getType();
//            Object o = field.get(this);
            Object oMap = this.get(name);
            JsonProperty annotation = field.getAnnotation(JsonProperty.class);
            if (null == oMap && null != annotation) {
                oMap = this.get(annotation.value());

            }
            if (null != oMap) {
                if (oMap instanceof Map) {

                    field.set(this, JsonUtil.toBean(oMap, field.getGenericType()));
                } else if (oMap instanceof Collection<?>) {
                    field.set(this, JsonUtil.toList(oMap, field.getGenericType()));
                } else {
                    if (oMap.getClass().equals(field.getGenericType())) {
                        field.set(this, oMap);
                    } else {
                        field.set(this, JsonUtil.toBean(oMap, field.getGenericType()));
                    }
                }
            }
            field.setAccessible(false);
        }
        Class<?> superclass = cls.getSuperclass();
        if (superclass.equals(Object.class) || superclass.equals(HashMap.class)) {
            return;
        }
        mapToEntity(superclass);
    }

    @SneakyThrows
    private void entityToMap(Class<?> cls) {
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            String name = field.getName();
            Object o = field.get(this);
            this.put(name, o);
        }
        Class<?> superclass = cls.getSuperclass();
        if (superclass.equals(Object.class) || superclass.equals(HashMap.class)) {
            return;
        }
        entityToMap(superclass);
    }
}
